import { defineStore } from 'pinia'
import mqtt from 'mqtt'
import { useUserStore } from '@/store'

export const useMqttStore = defineStore('mqtt', {
  state: () => ({
    url: undefined,
    client: undefined,
    // 订阅主题的集合，key为topic, value为接收到该topic时需要执行的回调
    subscribeMembers: {},
    currentId: null,
  }),
  actions: {
    // 获取密码
    async getCurrentId() {
      const userStore = useUserStore()
      // if (!userStore?.userInfo?.id) {
      //   await userStore.getUser()
      // }
      this.currentId = userStore.userInfo.id
      clientOptions['username'] = this.currentId
      clientOptions['clientId'] = `pc-${this.currentId}-${Date.now()}`
    },
    // 创建mqtt连接
    async connect(url) {
      if (!this.currentId) {
        await this.getCurrentId()
      }
      let client = mqtt.connect(url, clientOptions)
      client.on('connect', onConnect)
      client.on('reconnect', onReconnect)
      client.on('error', onError)
      client.on('message', onMessage)
      this.client = client
      this.url = url
    },

    disconnect() {
      this?.client?.end()
      this.client = undefined
      this.subscribeMembers = {}
      console.log(`服务器已断开连接！`)
    },

    /**
     *  订阅
     * @param topic            消息主题
     * @param subscribeOption  订阅设置
     * @param callback         接收消息的回调
     */
    subscribe({ topic, callback, subscribeOption }) {
      if (!this.client && this.url) {
        this.connect(this.url)
      }
      this.client.subscribe(
        topic,
        subscribeOption || { qos: clientOptions.qos },
        (error, granted) => {
          if (error) {
            console.log(`客户端: ${clientOptions.clientId}, 订阅主题: ${topic}失败: `, error)
          } else {
            console.log(`客户端: ${clientOptions.clientId}, 订阅主题: ${topic}成功`)
          }
        }
      )
      this.subscribeMembers[topic] = callback
    },

    /**
     *  取消订阅
     * @param topic  消息主题
     */
    unsubscribe(topic) {
      if (!this.client) {
        return
      }
      this.client.unsubscribe(topic, {}, (error, granted) => {
        if (error) {
          console.log(`客户端: ${clientOptions.clientId}, 取消订阅主题: ${topic}失败: `, error)
        } else {
          console.log(`客户端: ${clientOptions.clientId}, 取消订阅主题: ${topic}成功`)
        }
      })
      this.subscribeMembers[topic] = undefined
    },

    publish({ topic, message }) {
      if ((!this.client || !this.client.connected) && this.url) {
        this.connect(this.url)
      }
      this.client.publish(topic, message, { qos: clientOptions.qos }, (e) => {
        if (e) {
          console.log(
            `客户端: ${clientOptions.clientId}, 发送主题为: ${topic} 的消息, 发送失败: `,
            e
          )
        }
      })
    },
    resetMqtt() {
      this.$reset()
    },
  },
})

const clientOptions = {
  clean: true, // true: 清除会话, false: 保留会话
  connectTimeout: 4000, // 超时时间
  keepAlive: 60,
  clientId: 'pc_mqtt_client',
  // 认证信息
  username: 'yourUserName',
  password: 'yourPassword',
  // 开启log后，控制台会答应mqtt的调试日志
  // log: console.log.bind(console),
  qos: 1,
  path: '/mqtt',
}

const onConnect = (e) => {
  console.log(`客户端: ${clientOptions.clientId}, 连接emqx服务器成功:`, e)
}
const onReconnect = (error) => {
  console.log(`客户端: ${clientOptions.clientId}, 正在重连:`, error)
}
const onError = (error) => {
  console.log(`客户端: ${clientOptions.clientId}, 连接失败:`, error)
}
const onMessage = (topic, message) => {
  console.log(
    `客户端: ${clientOptions.clientId}, 接收到来自主题: ${topic} 的消息: `,
    message?.toString()
  )
  let callback = useMqttStore().subscribeMembers?.[topic]
  callback?.(topic, message?.toString())
}
